<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>样本集</title>

  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

  <style>
    html {
      height: 100vh;
    }

    body,
    #app {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    .sample-container {
      display: flex;
      gap: .625rem;
      width: 100%;
      height: 100%;
      padding: 1rem;
      box-sizing: border-box;
    }

    .card-box {
      padding: .625rem;
      border: .0625rem solid #ebeef5;
      border-radius: .25rem;
      background-color: #fff;
      color: #303133;
      transition: 0.3s;
      box-shadow: 0 .125rem .75rem 0 rgba(0, 0, 0, 0.1);
      box-sizing: border-box;
      overflow: hidden;
    }

    .tree-box {
      width: 18.75rem;
      height: 100%;
      background: #fff;
    }

    .filter-tree {
      height: calc(100% - 3.125rem);
      margin-top: .625rem;
      overflow: auto;
    }

    .custom-tree-node {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: .625rem;
      font-size: .875rem;
      padding-right: .5rem;
    }

    .el-tree-node__content {
      height: 2.25rem !important;
    }

    .tree-node-actions {
      display: none;
      transition: all 0.3s;
    }

    .el-tree-node__content:hover .tree-node-actions {
      display: flex;
      gap: .375rem;
    }

    .action-btn {
      font-size: .875rem;
      color: #909399;
      cursor: pointer;
      padding: .125rem;
      border-radius: .1875rem;
    }

    .action-btn:hover {
      background: #ecf5ff;
      color: #409EFF;
    }

    .main {
      width: calc(100% - 18.75rem);
      height: 100%;
    }

    .query-box {
      width: 100%;
      height: 3.75rem;
      margin-bottom: .625rem;
    }

    .image-container {
      width: 100%;
      height: calc(100% - 4.375rem);
    }

    .image-list {
      display: flex;
      flex-wrap: wrap;
      align-content: flex-start;
      align-items: flex-start;
      width: 100%;
      height: calc(100% - 2.5rem);
      overflow: auto;
    }

    .image-item {
      width: calc(92% / 5);
      height: 12.5rem;
      margin-bottom: 1.25rem;
    }

    .image-item:not(:nth-child(5n)) {
      margin-right: 2%;
    }

    .pagination-box {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 2.5rem;
      box-sizing: border-box;
    }
  </style>

</head>

<body>
  <div id="app">
    <div class="sample-container" v-loading="loading" element-loading-text="拼命加载中"
      element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)">
      <div class="tree-box card-box">
        <el-input placeholder="输入关键字进行过滤" v-model="filterText" clearable>
        </el-input>
        <el-tree ref="tree" class="filter-tree" :data="treeData" node-key="id" :props="defaultProps" default-expand-all
          :filter-node-method="filterNode" highlight-current :expand-on-click-node="false"
          @node-click="handleNodeClick">
          <div class="custom-tree-node" slot-scope="{ node, data }">
            <div v-if="data.isEdit">
              <!-- @keyup.enter.native="confirmEdit(node, data)" -->
              <el-input class="edit-input" v-focus placeholder="请输入内容" v-model="data.name" clearable size="mini"
                @blur="confirmEdit(node, data)" :autofocus="true">
              </el-input>
            </div>
            <div v-else>
              <span class="tree-node-label">
                <i :class="data.children ? 'el-icon-folder folder-icon' : 'el-icon-document file-icon'"></i>
                {{ node.label }}
              </span>
            </div>

            <div class="tree-node-actions">
              <span class="action-btn" @click.stop="addSiblingNode(data)" title="添加同级节点">
                <i class="el-icon-plus"></i>
              </span>
              <span class="action-btn" @click.stop="addChildNode(data)" title="添加子节点">
                <i class="el-icon-folder-add"></i>
              </span>
              <span class="action-btn" @click.stop="editNode(data)" title="编辑节点">
                <i class="el-icon-edit"></i>
              </span>
              <span class="action-btn" @click.stop="deleteNode(data)" title="删除节点">
                <i class="el-icon-delete"></i>
              </span>
            </div>
          </div>
        </el-tree>
      </div>
      <div class="main">
        <div class="query-box card-box">
          <el-form :inline="true">
            <el-form-item label="上传时间">
              <el-date-picker v-model="queryParams.startTime" type="date" placeholder="开始日期" value-format="yyyy-MM-dd">
              </el-date-picker>
              ~
              <el-date-picker v-model="queryParams.endTime" type="date" placeholder="结束日期" value-format="yyyy-MM-dd">
              </el-date-picker>
            </el-form-item>

            <el-form-item>
              <el-button type="primary" icon="el-icon-search" @click="getData">搜索</el-button>
            </el-form-item>
            <el-form-item>
              <el-button icon="el-icon-refresh" @click="reset">重置</el-button>
            </el-form-item>
            <el-form-item>
              <el-button type="success" icon="el-icon-upload2" @click="openImgDialog">图片上传</el-button>
            </el-form-item>
          </el-form>
        </div>
        <div class="image-container card-box">
          <div class="image-list">
            <el-image class="image-item" v-for="(item, index) in dataList" :key="item.id"
              :src="previewImgUrl + item.fileUrl" :preview-src-list="[previewImgUrl + item.fileUrl]">
            </el-image>
          </div>

          <el-pagination class="pagination-box" @size-change="handleSizeChange" @current-change="handleCurrentChange"
            :current-page="queryParams.pageNum" :page-sizes="[10, 20, 30]" :page-size="queryParams.pageSize"
            layout="total, sizes, prev, pager, next, jumper" :total="total">
          </el-pagination>
        </div>
      </div>

      <el-dialog title="图片上传" :visible.sync="dialogVisible" width="30%">
        <el-upload class="upload-box" ref="uploadRef" accept=".jpeg,.png,.jpg" action="" :auto-upload="false"
          :multiple="true" :file-list="fileList" list-type="picture" :limit="3" :on-remove="handleRemove"
          :on-change="handleFileChange">
          <el-button size="small" type="primary">点击上传</el-button>
          <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div> -->
        </el-upload>
        <span slot="footer" class="dialog-footer">
          <el-button @click="closeImgDialog">取 消</el-button>
          <el-button type="primary" @click="confirmUpload">确 定</el-button>
        </span>
      </el-dialog>
    </div>
  </div>
</body>

<!-- import Vue before Element -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>

  const dateFtt = (fmt, date) => {
    const o = {
      'M+': date.getMonth() + 1, // 月份
      'd+': date.getDate(), // 日
      'H+': date.getHours(), // 小时
      'm+': date.getMinutes(), // 分
      's+': date.getSeconds(), // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
      'S': date.getMilliseconds(), // 毫秒
      'W': ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][date.getDay()], // 星期
      'w': ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()], // 周几
    }
    if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) }
    for (const k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
    }
    return fmt
  };

  new Vue({
    el: '#app',
    directives: {
      // 注册一个局部的自定义指令 v-focus
      focus: {
        // 指令的定义
        inserted: function (el) {
          // 聚焦元素
          el.querySelector('input').focus()
        }
      }
    },
    data: function () {
      return {
        loading: false,
        filterText: '',
        currentSelectedNode: null,
        treeData: [
          {
            "id": 1,
            "name": "汉中大鲵",
            "parentId": null,
            "children": [
              {
                "id": 4,
                "name": "名字修改了",
                "parentId": 1,
                "children": [
                  {
                    "id": 8,
                    "name": "111",
                    "parentId": 4,
                    "children": null,
                    "createUser": null,
                    "createTime": null
                  }
                ],
                "createUser": null,
                "createTime": null
              },
              {
                "id": 5,
                "name": "12",
                "parentId": 1,
                "children": null,
                "createUser": null,
                "createTime": null
              }
            ],
            "createUser": null,
            "createTime": null
          },
          {
            "id": 2,
            "name": "河南大鲵",
            "parentId": null,
            "children": [
              {
                "id": 6,
                "name": "12",
                "parentId": 2,
                "children": null,
                "createUser": null,
                "createTime": null
              },
              {
                "id": 7,
                "name": "13",
                "parentId": 2,
                "children": null,
                "createUser": null,
                "createTime": null
              }
            ],
            "createUser": null,
            "createTime": null
          },
          {
            "id": 3,
            "name": "张家界大鲵",
            "parentId": null,
            "children": null,
            "createUser": null,
            "createTime": null
          }
        ],
        defaultProps: {
          children: 'children',
          label: 'name'
        },
        queryParams: {
          startTime: dateFtt('yyyy-MM-dd', new Date()),
          endTime: dateFtt('yyyy-MM-dd', new Date()),
          pageNum: 1,
          pageSize: 10,
          folderList: [],
        },
        dataList: [
          {
            id: 1,
            fileUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
          },
        ],
        previewImgUrl: 'http://10.10.200.132:9000/test/',
        total: 0,
        dialogVisible: false,
        fileList: [],
      }
    },
    watch: {
      filterText(val) {
        this.$refs.tree.filter(val);
      }
    },
    mounted() {
      this.getTreeData();
    },
    methods: {
      getTreeData() {
        axios.get("http://localhost:80/business/folderManage/folderTreeList").then(res => {
          console.log(res, '树结构');
          if (res.status == 200) {
            this.treeData = res.data.data;
            this.currentSelectedNode = this.treeData[0];
            this.$nextTick(() => {
              this.$refs.tree.setCurrentKey(this.currentSelectedNode.id);
            })
            this.queryParams.folderList = [this.currentSelectedNode.id];
            this.getData();
          }
        })
      },
      filterNode(value, data) {
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
      },
      handleNodeClick(data) {
        console.log('点击节点', data);
        this.currentSelectedNode = data;
        this.queryParams.folderList = [this.currentSelectedNode.id];
        this.getData();
      },
      // 添加同级节点
      addSiblingNode(data) {
        const node = this.$refs.tree.getNode(data);
        const parent = node.parent;
        const level = node.level;

        if (level === 1) {
          // 根节点层级
          const newNode = {
            id: undefined,
            name: '新根节点',
            isEdit: true,
            children: []
          };
          this.treeData.push(newNode);
        } else {
          // 非根节点层级
          const newNode = {
            id: undefined,
            name: '新同级节点',
            isEdit: true
          };
          parent.data.children.push(newNode);
        }
      },
      // 添加子节点
      addChildNode(data) {
        console.log('新增子节点', data);

        if (!data.children) {
          this.$set(data, 'children', []);
        }

        const newNode = {
          id: undefined,
          name: '新子节点',
          isEdit: true
        };

        data.children.push(newNode);
        this.currentSelectedNode = newNode;
      },
      // 编辑节点
      editNode(data) {
        console.log('编辑节点', data);
        this.$set(data, 'isEdit', true);
        this.currentSelectedNode = data;
      },
      // 确认编辑
      confirmEdit(node, data) {
        console.log('confirmEdit', node, data);
        this.$set(data, 'isEdit', false);
        if (!data.name.trim()) {
          data.name = '未命名节点';
        }
        const parentNode = node.parent.data;

        let params = {
          parentId: parentNode.id,
          name: data.name,
          id: data.id
        };
        console.log(params);

        const formData = new FormData();

        if (data.id) {
          // 编辑
          formData.append('name', data.name);
          formData.append('id', data.id);
          axios.post('http://localhost:80/business/folderManage/updateFolder', formData).then(res => {
            console.log(res);
            if (res.status === 200) {
              this.$message.success('修改成功');
              this.getTreeData();
            }
          }).catch(err => {
            console.log(err);
            this.$message.error('修改失败');
          })
        } else {
          // 新增
          formData.append('name', data.name);
          formData.append('parentId', parentNode.id);
          axios.post('http://localhost:80/business/folderManage/addFolder', formData).then(res => {
            console.log(res);
            if (res.status === 200) {
              this.$message.success('添加成功');
              this.getTreeData();
            }
          }).catch(err => {
            console.log(err);
            this.$message.error('添加失败');
          })
        }

      },
      // 删除节点
      deleteNode(data) {
        this.$confirm('确定要删除该节点及其所有子节点吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          // const node = this.$refs.tree.getNode(data);
          // const parent = node.parent;
          // const children = parent.data.children || parent.data;
          // const index = children.findIndex(d => d.id === data.id);
          // children.splice(index, 1);
          // this.$message.success('节点删除成功');

          const formData = new FormData();
          formData.append('folderId', data.id);
          axios.post('http://localhost:80/business/folderManage/deleteFolder', formData).then(res => {
            if (res.status === 200) {
              this.$message.success('删除成功');
              this.getTreeData();
            } else {
              this.$message.error('删除失败');
            }
          }).catch(() => {
            this.$message.error('删除失败');
          });

        }).catch(() => {
          this.$message.info('已取消删除');
        });
      },
      getData() {
        this.dataList = [];
        this.loading = true;

        axios.post('http://localhost/business/sampleSet/list', this.queryParams).then(res => {
          console.log(res, '列表数据');
          if (res.status == 200) {
            this.loading = false;
            this.dataList = res.data.rows;
            this.total = res.data.total;
          } else {
            this.loading = false;
          }
        }).catch(() => {
          this.loading = false;
        });
      },
      reset() {
        console.log('reset');
        this.queryParams = {
          startTime: dateFtt('yyyy-MM-dd', new Date()),
          endTime: dateFtt('yyyy-MM-dd', new Date()),
          pageNum: 1,
          pageSize: 10,
          folderList: this.currentSelectedNode && this.currentSelectedNode.id ? [this.currentSelectedNode.id] : [],
        };
        this.getData();
      },
      handleSizeChange(val) {
        console.log(`每页 ${val} 条`);
        this.queryParams.pageSize = val;
        this.getData();
      },
      handleCurrentChange(val) {
        console.log(`当前页: ${val}`);
        this.queryParams.pageNum = val;
        this.getData();
      },
      openImgDialog() {
        console.log('openImgDialog');
        this.dialogVisible = true;
      },
      closeImgDialog() {
        this.dialogVisible = false;
        this.$refs.uploadRef.clearFiles();
        this.fileList = [];
      },
      checkFileType(file) {
        const fileName = file.name
        const fileType = fileName.substring(fileName.lastIndexOf('.'))
        // jpeg,.png,.jpg,.bmp,.gif
        const imgTypes = ['.jpg', '.png', '.jpeg'];
        if (!imgTypes.includes(fileType)) {
          this.$message.error(
            '不是.jpeg,.png,.jpg文件，请上传正确的图片类型'
          )
          return false;
        } else {
          return true;
        }
      },
      handleRemove(file, fileList) {
        console.log('删除图片', file, fileList);
        this.fileList = fileList;
      },
      handleFileChange(file, fileList) {
        console.log('选择图片', file, fileList);
        // let isImage = this.checkFileType(file);
        this.fileList = fileList;
      },
      confirmUpload() {
        console.log('确认上传', this.fileList);

        if (this.fileList.length === 0) {
          this.$message.warning('请选择图片后再上传');
          return;
        }

        const formData = new FormData();
        this.fileList.forEach(file => {
          formData.append('files', file.raw);
        });
        formData.append('folderId', this.currentSelectedNode.id);

        axios.post('http://localhost:80/business/sampleSet/uploadFiles', formData).then(res => {
          console.log('上传成功', res);
          this.$message.success('上传成功');
          this.$refs.uploadRef.clearFiles();
          this.dialogVisible = false;
          this.fileList = [];
          this.getData();
        }).catch(err => {
          console.log('上传失败', err);
        });

      },
    },
  })
</script>

</html>